package cn.itguy.mobileguard.activity;

import android.app.Dialog;
import android.app.ListActivity;
import android.os.Bundle;
import android.os.AsyncTask;
import android.view.View;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.gesture.GestureLibrary;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.ArrayAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;

import java.util.Map;
import java.util.Collections;
import java.util.HashMap;
import java.util.Comparator;
import java.util.Set;
import java.io.File;

import cn.itguy.mobileguard.IMGPreferences;
import cn.itguy.mobileguard.R;

public class GestureBuilderActivity extends ListActivity {

	private static final int STATUS_SUCCESS = 0;
	private static final int STATUS_CANCELLED = 1;
	private static final int STATUS_NOT_LOADED = 2;

	private static final int MENU_ID_REMOVE = 1;

	private static final int REQUEST_NEW_GESTURE = 1;

	// Type: long (id)
	private static final String GESTURES_INFO_ID = "gestures.info_id";

	private IMGPreferences preferences;
	
	private File mStoreFile;

	private final Comparator<NamedGesture> mSorter = new Comparator<NamedGesture>() {
		public int compare(NamedGesture object1, NamedGesture object2) {
			return object1.name.compareTo(object2.name);
		}
	};

	private static GestureLibrary sStore;

	private GesturesAdapter mAdapter;
	private GesturesLoadTask mTask;
	private TextView mEmpty;

	private Dialog mRenameDialog;
	private NamedGesture mCurrentRenameGesture;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		preferences = IMGPreferences.getInstance(this);
		mStoreFile = new File(getFilesDir(), "gestures");

		setContentView(R.layout.gestures_list);

		((TextView) findViewById(R.id.tv_title))
				.setText(R.string.titleText_select_gesture);

		Button btn_left = (Button) findViewById(R.id.btn_left);
		btn_left.setVisibility(View.VISIBLE);
		btn_left.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				finish();
			}
		});

		mAdapter = new GesturesAdapter(this);
		setListAdapter(mAdapter);

		if (sStore == null) {
			sStore = GestureLibraries.fromFile(mStoreFile);
		}
		mEmpty = (TextView) findViewById(android.R.id.empty);
		loadGestures();

		registerForContextMenu(getListView());
	}

	static GestureLibrary getStore() {
		return sStore;
	}

	public void reloadGestures(View v) {
		loadGestures();
	}

	public void addGesture(View v) {
		Intent intent = new Intent(this, CreateGestureActivity.class);
		startActivityForResult(intent, REQUEST_NEW_GESTURE);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case REQUEST_NEW_GESTURE:
				loadGestures();
				break;
			}
		}
	}

	private void loadGestures() {
		if (mTask != null
				&& mTask.getStatus() != GesturesLoadTask.Status.FINISHED) {
			mTask.cancel(true);
		}
		mTask = (GesturesLoadTask) new GesturesLoadTask().execute();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		if (mTask != null
				&& mTask.getStatus() != GesturesLoadTask.Status.FINISHED) {
			mTask.cancel(true);
			mTask = null;
		}

		cleanupRenameDialog();
	}

	private void checkForEmpty() {
		if (mAdapter.getCount() == 0) {
			mEmpty.setText(R.string.gestures_empty);
		}
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);

		if (mCurrentRenameGesture != null) {
			outState.putLong(GESTURES_INFO_ID,
					mCurrentRenameGesture.gesture.getID());
		}
	}

	@Override
	protected void onRestoreInstanceState(Bundle state) {
		super.onRestoreInstanceState(state);

		long id = state.getLong(GESTURES_INFO_ID, -1);
		if (id != -1) {
			final Set<String> entries = sStore.getGestureEntries();
			out: for (String name : entries) {
				for (Gesture gesture : sStore.getGestures(name)) {
					if (gesture.getID() == id) {
						mCurrentRenameGesture = new NamedGesture();
						mCurrentRenameGesture.name = name;
						mCurrentRenameGesture.gesture = gesture;
						break out;
					}
				}
			}
		}
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		
		preferences.setAllclearGestureId(id);
		mAdapter.checkedItemId = id;
		mAdapter.notifyDataSetChanged();
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenu.ContextMenuInfo menuInfo) {

		super.onCreateContextMenu(menu, v, menuInfo);

		AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
		menu.setHeaderTitle(((TextView) info.targetView.findViewById(R.id.tv_name)).getText());

		menu.add(0, MENU_ID_REMOVE, 0, R.string.gestures_delete);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		final AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item
				.getMenuInfo();
		final NamedGesture gesture = (NamedGesture) menuInfo.targetView
				.getTag();

		switch (item.getItemId()) {
		case MENU_ID_REMOVE:
			deleteGesture(gesture);
			return true;
		}

		return super.onContextItemSelected(item);
	}

	private void cleanupRenameDialog() {
		if (mRenameDialog != null) {
			mRenameDialog.dismiss();
			mRenameDialog = null;
		}
		mCurrentRenameGesture = null;
	}

	private void deleteGesture(NamedGesture gesture) {
		sStore.removeGesture(gesture.name, gesture.gesture);
		sStore.save();
		
		if (mAdapter.checkedItemId == gesture.gesture.getID()) {
			preferences.getSp().edit().remove(IMGPreferences.PREFERENCES_KEY_ALLCLEAR_GESTURE_ID).commit();
			mAdapter.checkedItemId = -1l;
		}

		final GesturesAdapter adapter = mAdapter;
		adapter.setNotifyOnChange(false);
		adapter.remove(gesture);
		adapter.sort(mSorter);
		checkForEmpty();
		adapter.notifyDataSetChanged();

		Toast.makeText(this, R.string.gestures_delete_success,
				Toast.LENGTH_SHORT).show();
	}

	private class GesturesLoadTask extends
			AsyncTask<Void, NamedGesture, Integer> {
		private int mThumbnailSize;
		private int mThumbnailInset;
		private int mPathColor;

		@Override
		protected void onPreExecute() {
			super.onPreExecute();

			final Resources resources = getResources();
			mPathColor = resources.getColor(R.color.dark_grey);
			mThumbnailInset = (int) resources
					.getDimension(R.dimen.gesture_thumbnail_inset);
			mThumbnailSize = (int) resources
					.getDimension(R.dimen.gesture_thumbnail_size);

			findViewById(R.id.addButton).setEnabled(false);
			findViewById(R.id.reloadButton).setEnabled(false);

			mAdapter.setNotifyOnChange(false);
			mAdapter.clear();
		}

		@Override
		protected Integer doInBackground(Void... params) {
			if (isCancelled())
				return STATUS_CANCELLED;

			final GestureLibrary store = sStore;

			if (store.load()) {
				for (String name : store.getGestureEntries()) {
					if (isCancelled())
						break;

					for (Gesture gesture : store.getGestures(name)) {
						final Bitmap bitmap = gesture.toBitmap(mThumbnailSize,
								mThumbnailSize, mThumbnailInset, mPathColor);
						final NamedGesture namedGesture = new NamedGesture();
						namedGesture.gesture = gesture;
						namedGesture.name = name;

						mAdapter.addBitmap(namedGesture.gesture.getID(), bitmap);
						publishProgress(namedGesture);
					}
				}

				return STATUS_SUCCESS;
			}

			return STATUS_NOT_LOADED;
		}

		@Override
		protected void onProgressUpdate(NamedGesture... values) {
			super.onProgressUpdate(values);

			final GesturesAdapter adapter = mAdapter;
			adapter.setNotifyOnChange(false);

			for (NamedGesture gesture : values) {
				adapter.add(gesture);
			}

			adapter.sort(mSorter);
			adapter.notifyDataSetChanged();
		}

		@Override
		protected void onPostExecute(Integer result) {
			super.onPostExecute(result);

			findViewById(R.id.addButton).setEnabled(true);
			findViewById(R.id.reloadButton).setEnabled(true);
			checkForEmpty();
		}
	}

	static class NamedGesture {
		String name;
		Gesture gesture;
	}

	private class GesturesAdapter extends ArrayAdapter<NamedGesture> {

		private final LayoutInflater mInflater;
		private final Map<Long, Drawable> mThumbnails = Collections
				.synchronizedMap(new HashMap<Long, Drawable>());

		private long checkedItemId;
		
		public GesturesAdapter(Context context) {
			super(context, 0);
			mInflater = (LayoutInflater) context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			checkedItemId = preferences.getAllclearGestureId();
		}

		void addBitmap(Long id, Bitmap bitmap) {
			mThumbnails.put(id, new BitmapDrawable(bitmap));
		}

		@Override
		public long getItemId(int position) {
			return getItem(position).gesture.getID();
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView == null) {
				convertView = mInflater.inflate(R.layout.gestures_item, parent,
						false);
			}

			NamedGesture gesture = getItem(position);
			TextView label = (TextView) convertView.findViewById(R.id.tv_name);
			label.setText(gesture.name);
			
			convertView.setTag(gesture);
			
			ImageView iv_gesture_thumbnail = (ImageView) convertView.findViewById(R.id.iv_gesture_thumbnail);
			iv_gesture_thumbnail.setImageDrawable(mThumbnails.get(gesture.gesture.getID()));
			
			CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.checkBox);
			
			if (checkedItemId != -1 && checkedItemId == gesture.gesture.getID()) {
				checkBox.setChecked(true);
			} else {
				checkBox.setChecked(false);
			}

			if (getCount() == 1) {
				convertView
						.setBackgroundResource(R.drawable.selector_small_corner_listview_single_item);
			} else if (position == 0) {
				convertView
						.setBackgroundResource(R.drawable.selector_small_corner_listview_top_item);
			} else if (position == getCount() - 1) {
				convertView
						.setBackgroundResource(R.drawable.selector_small_corner_listview_bottom_item);
			} else {
				convertView
						.setBackgroundResource(R.drawable.selector_small_corner_listview_common_item);
			}

			return convertView;
		}
	}
}
